Create VM: default install source to a storage pool marked for ISOs#2683
Create VM: default install source to a storage pool marked for ISOs#2683schaerfl wants to merge 1 commit into
Conversation
The "Local install media" installation source is a free-path typeahead that always starts at the filesystem root, so users with a dedicated ISO directory (e.g. a dir pool at /var/lib/libvirt/iso) must navigate down from "/" on every VM creation. Let the user mark a storage pool as installation media on the pool's Overview tab. When such a pool exists, the Create VM dialog pre-fills the local install-media source with the pool's target directory, so the path picker opens inside the ISO directory. With no pool marked, behaviour is unchanged and the field still defaults to "/". libvirt storage pools have no <metadata> element to persist such a flag (unlike domains), and the pool type is a fixed enum, so the marks are stored host-side in a small Cockpit-owned file keyed by pool UUID (/etc/cockpit/machines/install-media-pools.json for the system connection, ~/.config/cockpit/machines/ for the session connection), mirroring how the code already reads /etc/libvirt/qemu.conf via cockpit.file(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
We are currently working on improving this with a new File Chooser widget, see cockpit-project/cockpit#23380. Here is a demo of how this would look in Cockpit Machines. I'll check your PR here to see how this interacts with your proposal. |
With the File Chooser, checking the "Use for installation media" flag would add the directory of the pool to the shortcuts in the sidebar. All of them would be shown. But instead of making this a property of a storage pool, I would add general bookmarks to the File Chooser dialog. I think the checkbox on the storage pool page is too far away from where it's effect can be observed. Managing bookmarks right in the dialog should give the same benefits and be easier to discover and understand. Where to store the bookmarks (browser storage, host file system) would still need to be answered. For bookmarks, my initial reaction would be to store them in browser localStorage. They are sufficiently "personal" and much less "system config". Thanks for the contribution! What do you think? |
|
I've setup/administrated some Proxmox Environments and inspired myself from the ISO directory selection. Its kinda similar to my implementation. When setting up a disk (in Cockpit a storage pool) you choose the contents of the disk and when you select ISO, it appears as a selectable source for ISOs in the VM setup and automatically gives you the ISO options which are on the disk / in the selected path. Maybe this way of implementation is a little to complicated, as you mentioned correctly. I really like the File Chooser with automatic search and listing for .iso files, aswell as the bookmark idea and i totally agree, that the bookmark idea is more intuitive and easier to find. Regarding the browsers localStorage... I had this thought aswell but scratched it. |
Problem
When creating a VM with Local install media (ISO image or distro install tree), the Installation source field is a free-path typeahead that always opens at the filesystem root (
/). Users who keep their ISOs in a dedicated location — very commonly adirstorage pool at e.g./var/lib/libvirt/iso— have to navigate down from/(/,/var,/var/lib, …) every single time they create a VM, even though they already told libvirt where their install media lives when they defined that pool.There is currently no way to say "this pool holds my installation media, start there."
What this does
Let the user mark a storage pool as installation media with a toggle on the pool's Overview tab (shown for
dirandnetfspools).When at least one pool is marked, the Create VM → Local install media source field is pre-filled with that pool's target directory, so the path picker opens directly inside the ISO directory and the user only has to pick the image.
With no pool marked, behaviour is completely unchanged — the field still defaults to
/. The feature is purely opt-in.Why it's built this way
Where the marker lives
The natural place to store "this pool is for ISOs" would be on the pool itself. That isn't possible:
<metadata>element. Domains have<metadata>+virDomainSetMetadata, but pools do not. The only escape hatch — storage-pool namespaces — is documented by libvirt as carrying "no support guarantees… should never be used in production."typeis a fixed enum (dir,netfs,iscsi, …), validated on define, so a syntheticiso-dirtype is rejected.So the marker is stored host-side in a small Cockpit-owned JSON file keyed by pool UUID:
system/etc/cockpit/machines/install-media-pools.json(written withsuperuser: "try")session~/.config/cockpit/machines/install-media-pools.json{ "pools": ["7fb3a128-ac8a-4f6e-8e10-581c2321b6a4"] }This mirrors existing cockpit-machines behaviour — the code already reads
/etc/libvirt/qemu.confviacockpit.file(...)(src/helpers.ts) and writes host files via.replace(). Keying on UUID (not name) means renaming a pool is safe; a UUID whose pool no longer exists is simply ignored and pruned on the next write.Implementation (3 files)
src/libvirtApi/installMediaPools.ts(new) —getInstallMediaPools()/setInstallMediaPool()read and atomically update the config viacockpit.file(path, { syntax: JSON }).modify(...), per connection.src/components/storagePools/storagePoolOverviewTab.tsx— aSwitch("Use for installation media") fordir/netfspools that have a UUID, with an optimistic update that reverts if the write fails.src/components/create-vm-dialog/createVmDialog.tsx—prefillInstallMediaSource()runs both on dialog mount and when the user switches the installation type to local media; it sets the source to the marked pool'starget/pathonly when the user hasn't supplied/typed a source.One subtlety worth flagging for review:
FileAutoCompletereads itsvalueprop only in its constructor (nocomponentDidUpdate), so an async pre-fill arriving after mount is otherwise ignored. The dialog gives that field a one-shotkey(installMediaSourceKey) that bumps exactly once when the pre-fill lands, forcing a single remount so the field picks up the value — without remounting on every keystroke (which would steal focus).Trade-offs / things to discuss
I want to be upfront about the design decisions rather than oversell — the core UX win is clear, but there are real points for maintainers to weigh:
Testing
Verified manually end-to-end on against a live system (Arch Linux) connection: marking the pool writes the config file; the Create VM dialog pre-fills
/var/lib/libvirt/iso/and the picker opens there; un-marking reverts to/.npm run eslintis clean and there are no new type errors.Integration tests (
test/check-machines-storage-pools/check-machines-create) are not yet included — I'd like to confirm the design direction (especially the host-side config file) before writing them, hence opening as a draft. Happy to add them, or to split the rationale into a separate issue first if that's preferred.Screenshots
Storage Pool config:
Create VM autofill in dialog:
🤖 Generated with Claude Code